<template>
	<div class="borderBox gomoku-div">
		<!--绘制棋盘,绘制一次-->
		<canvas canvas-id="chess1" :style="{width: canvasW+'px', height: canvasH+'px'}"></canvas>
		
		<!--游戏结束提示-->
		<div class="game-div" :style="{top: canvasW/2+'px'}"
			@click.stop="replayGame" v-if="gameOver">
			<p class="over">游戏结束</p>
			<p class="again">重新开始</p>
		</div>
		
		
		<!--绘制棋子-->
		<canvas canvas-id="chess2" :style="{width: canvasW+'px', height: canvasH+'px'}"
			@click.stop='xiaqi'></canvas>
		
		<div class="again" @click.stop="replayGame">重新开始</div>
	</div>
</template>

<script>
import {showToast,showModal} from '@/utils/index';
var chessBoard = [];  //数组，存储棋盘落子情况
var chessColor = true;  //棋子颜色， 默认开始为黑色
var wins_arr = []; //赢法数组
var win_index = 0;  //赢法种类的索引
//赢法的统计数组
var myWin = [];   //我方的
var computerWin = [];   //计算机方的
var audio; //音频组件
export default{
	data(){
		return{
			canvasW: 300,
			canvasH: 300,
			margin_space: 15,  //距离四周的间距
			increse_space: '', //增长步长,两条线之间的间距
			ctx2: '', //落棋子绘制
			gameOver: false,  //游戏是否结束
		}
	},
	mounted(){
		let sysInfo = uni.getSystemInfoSync();
		let windowWidth = sysInfo.windowWidth;
		this.canvasW = this.canvasH = windowWidth - 20; //左右都留10px
		this.increse_space = (this.canvasW - this.margin_space*2)/15;
		
		this.ctx2 = uni.createCanvasContext('chess2');
		this.drawChess();
		this.initWinMethods();
		this.initAudio();
	},
	methods: {
		//音频
		initAudio(){
			audio = uni.createInnerAudioContext();
			audio.src = "/static/audio/chess.mp3";
		},
		//重玩游戏
		replayGame(){
			//清除画布2
			this.ctx2.clearRect(0, 0, this.canvasW, this.canvasH);
			this.ctx2.draw();
			chessBoard = [];
			chessColor = true;  //棋子颜色， 默认开始为黑色
			//赢法的统计数组
			this.gameOver = false;  //游戏结束
			//初始化赢法统计数组
			for(var i=0; i<win_index; i++){
				myWin[i] = 0;
				computerWin[i] = 0;
			}
		},
		//绘制棋盘
		drawChess(){
			var margin_space = this.margin_space; //距离四周的间距
			var increse_space = this.increse_space;   //增长步长,两条线之间的间距
			let ctx1 = uni.createCanvasContext('chess1');
			ctx1.setStrokeStyle('#2a2929');  //画线颜色
			ctx1.setLineWidth(1);
			for(var i=margin_space; i<this.canvasW; i+=increse_space){
				//绘制横线
				ctx1.moveTo(margin_space, i);
				ctx1.lineTo(this.canvasW-margin_space, i);  
				//绘制竖线
				ctx1.moveTo(i, margin_space);
				ctx1.lineTo(i, this.canvasW-margin_space);
			}
			ctx1.stroke();
			ctx1.draw();
		},
		/**绘制棋子
		 * x坐标
		 * y坐标
		 * 棋子颜色, 默认黑色棋子
		****/
		drawChessMan(x=0, y=0){
			let ctx2 = this.ctx2;
		
			var r_x = this.margin_space + x *this.increse_space;  //圆心x坐标
			var r_y = this.margin_space + y *this.increse_space;  //圆心y坐标
			ctx2.save();
			ctx2.beginPath();
			//创建渐变，中心点稍微便宜到右上角
			var grd=ctx2.createCircularGradient(r_x+2 ,r_y-2, 10); 
			if(chessColor){
				grd.addColorStop(0, '#636766');
				grd.addColorStop(1, '#0A0A0A');
			}else{
				grd.addColorStop(0, '#F9F9F9');
				grd.addColorStop(1, '#D1D1D1');
			}
			
			ctx2.arc(r_x,r_y, 10, 0, 2*Math.PI);
			ctx2.setFillStyle(grd);
			ctx2.fill();
			ctx2.closePath();
			ctx2.restore();
			ctx2.draw({reserve: true});
		},
		//点击棋盘
		xiaqi(e){
			if(this.gameOver && !chessColor){
				return;
			};
			var clientX = e.clientX;
			var clientY = e.clientY;
			//棋子索引
			clientX = (clientX-15)<0? 0: (clientX-15);
			clientY = (clientY-15)<0? 0: (clientY-15);
			var x = (clientX / this.increse_space).toFixed();
			var y = (clientY / this.increse_space).toFixed();
			
			var tmp_obj = {
				x: x, 
				y: y,
				color:1  //1 表示下的是黑色
			}
			//是否有一个元素满足坐标相等
			var pass = chessBoard.some(function(ele, index){
				return (ele.x==x && ele.y==y);
			});
			if(pass){
				showToast('该处已落子');
				return;
			};
			
			chessBoard.push(tmp_obj);  //该坐标没有被使用，可以落子
			audio.play();
			this.drawChessMan(x,y);
			
			//遍历所有赢法
			for(var k=0; k<win_index; k++){
				if(wins_arr[x][y][k]){
					myWin[k]++;
					computerWin[k] = 6; //计算机这种赢法不可能赢
					if(myWin[k]===5){ //这种赢法正好有5个棋子，表示赢了
						showModal(还是我厉害,赢啦);
						this.gameOver = true;
						break;
					}
				}
			}
			if(!this.gameOver){
				chessColor = !chessColor; //取反
				this.computerAI();  //计算机自动下棋
			}
		},
		//计算机AI自动下棋
		computerAI(){
			var myScore = [];  //我方得分
			var computerScore = [];  //计算机得分
			var maxScore =0;  //计算最高分数
			var x_pos = 0, y_pos = 0; //保存最高分点的坐标
			//初始化得分
			for(var i=0; i<15; i++){
				myScore[i] = [];
				computerScore[i] = [];
				for(var j=0; j<15; j++){
					myScore[i][j] = 0;
					computerScore[i][j] = 0;
				}
			}
			//遍历整个棋盘
			for(var i=0; i<15; i++){
				for(var j=0; j<15; j++){
					//是否有一个元素满足坐标相等
					let pass = chessBoard.some(function(ele, index){
						return (ele.x==i && ele.y==j);
					});
					if(!pass){  //表示该点未落下棋子，为空闲点
						for(var k=0; k<win_index; k++){
							if(wins_arr[i][j][k]){  //该落下点是有价值的，可以赢的
								//对黑色棋子进行拦截
								switch(myWin[k]){
									case 1: myScore[i][j] += 200;  
											break;
									case 2: myScore[i][j] += 400;  
											break;
									case 3: myScore[i][j] += 2000;  
											break;
									case 4: myScore[i][j] += 10000;  
											break;
								}
								//使计算机落下棋子更有效
								switch(computerWin[k]){
									case 1: computerScore[i][j] += 220;  
											break;
									case 2: computerScore[i][j] += 420;  
											break;
									case 3: computerScore[i][j] += 2100;  
											break;
									case 4: computerScore[i][j] += 20000;  
											break;
								}
							}
						}
						//得到了最高分数的点
						if(myScore[i][j] > maxScore){
							maxScore = myScore[i][j];
							x_pos = i;
							y_pos = j;
						}else if(myScore[i][j] == maxScore){
							if(computerScore[i][j] > computerScore[x_pos][y_pos]){
								x_pos = i;
								y_pos = j;
							}
						}
						if(computerScore[i][j] > maxScore){
							maxScore = computerScore[i][j];
							x_pos = i;
							y_pos = j;
						}else if(computerScore[i][j] == maxScore){
							if(myScore[i][j] > myScore[x_pos][y_pos]){
								x_pos = i;
								y_pos = j;
							}
						}
					}
				}
			};
			this.drawChessMan(x_pos, y_pos);
			var tmp_obj = {
				x: x_pos, 
				y: y_pos,
				color:2  //2 表示下的是白色
			}
			chessBoard.push(tmp_obj);  //落子
			//遍历所有赢法
			for(var k=0; k<win_index; k++){
				if(wins_arr[x_pos][y_pos][k]){
					computerWin[k]++;
					myWin[k] = 6; //我方这种赢法不可能赢
					if(computerWin[k]===5){ //这种赢法正好有5个棋子，表示赢了
						showModal('计算机超级牛逼啊，我被打败了');
						this.gameOver = true;
						break;
					}
				}
			}
			if(!this.gameOver){
				chessColor = !chessColor; //取反
			}
		},
		//初始化赢法
		initWinMethods(){
			//赢法数组初始化
			for(var i=0; i<15; i++){
				wins_arr[i] = [];
				for(var j=0; j<15; j++){
					wins_arr[i][j] = [];
				}
			}
			
			//统计所有的横线赢法
			for(var i=0; i<15; i++){
				for(var j=0; j<11; j++){
					for(var k=0; k<5; k++){
						wins_arr[i][j+k][win_index] = true;
					}
					/**
					 * 第0中赢法，最后一位表示第0种
					 * 前两位表示坐标，
					 * 正好[0,0],[0,1],[0,2],[0,3],[0,4]五个坐标连成一条线
					 * **/
					//wins_arr[0][0][0] =  true
					//wins_arr[0][1][0] =  true
					//wins_arr[0][2][0] =  true
					//wins_arr[0][3][0] =  true
					//wins_arr[0][4][0] =  true
				
					//第1中赢法
					//wins_arr[0][1][1] =  true
					//wins_arr[0][2][1] =  true
					//wins_arr[0][3][1] =  true
					//wins_arr[0][4][1] =  true
					//wins_arr[0][5][1] =  true
					win_index++;
				}
			}
			//统计所有的竖线赢法
			for(var i=0; i<15; i++){
				for(var j=0; j<11; j++){
					for(var k=0; k<5; k++){
						wins_arr[j+k][i][win_index] = true;
					}
					win_index++;
				}
			}
			//统计所有的正斜线赢法
			for(var i=0; i<11; i++){
				for(var j=0; j<11; j++){
					for(var k=0; k<5; k++){
						wins_arr[i+k][j+k][win_index] = true;
					}
					win_index++;
				}
			}
			//统计所有的反斜线赢法
			for(var i=0; i<11; i++){
				for(var j=14; j>3; j--){
					for(var k=0; k<5; k++){
						wins_arr[i+k][j-k][win_index] = true;
					}
					win_index++;
				}
			}
			//console.log(win_index)共573种赢法
			
			//初始化赢法统计数组
			for(var i=0; i<win_index; i++){
				myWin[i] = 0;
				computerWin[i] = 0;
			}
		},
	}
}
</script>

<style lang="less" scoped>
.gomoku-div{
	position: relative;
	width: 100vw;
	height: 100vh;
	canvas{
		position: absolute;
		left: 10px;
		/* top: 50%;
		transform: translateY(-50%); */
	}
}

.game-div{
	padding: 20upx 30upx;
	min-width: 400upx;
	position: absolute;
	background: rgba(0,0,0,0.8);
	transform: translate(-50%, -50%);
	left: 50%;
	display: inline-block;
	z-index: 99;
	color: #fff;
	border-radius: 12upx;
	text-align: center;
	&:active{
		box-shadow: 10upx 10upx 10upx #999;
	}
	p{
		line-height: 60upx;
	}
}

div.again{
	position: absolute;
	bottom: 20upx;
	left: 50%;
	transform: translateX(-50%);
	width: 300upx;
	line-height: 80upx;
	border-radius: 40upx;
	background: #38adfd;
	color: #fff;
	text-align: center;
}
</style>
